//  This file is part of Swordbible - http://www.swordwarrior.net
//  Copyright (C) 2003-2009 Manu Mital mital.manu@gmail.com

//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2, or (at your option)
//  any later version.

//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.

//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.


// BibleForm.cpp : implementation file
//

#include <stdafx.h>
#include "SwordBible.h"
#include "BibleForm.h"
#include ".\bibleform.h"


// CBibleForm
int CBibleForm::formIns = 0; // static variable to keep track of 
							// creation of top and bottom form
CRichEditCtrl* CBibleForm::pControl = NULL;

IMPLEMENT_DYNCREATE(CBibleForm, CFormView)

CBibleForm::CBibleForm()
	: CFormView(CBibleForm::IDD)
{
	isSheet = FALSE;					// initialize to false
	formIns++;
	objCount = formIns;                // which instance of form (top or bottom) ?
	m_pMyPropSheet = NULL;

}

CBibleForm::~CBibleForm()
{
	//CoUninitialize();

	if (m_pMyPropSheet)
	delete m_pMyPropSheet;

	formIns--;

}

void CBibleForm::DoDataExchange(CDataExchange* pDX)
{
	CFormView::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CBibleForm, CFormView)
	ON_WM_SIZE()
	ON_MESSAGE(WM_PRINT_CONTROL, OnPrintMessage)
END_MESSAGE_MAP()


// CBibleForm diagnostics

#ifdef _DEBUG
void CBibleForm::AssertValid() const
{
	CFormView::AssertValid();
}

void CBibleForm::Dump(CDumpContext& dc) const
{
	CFormView::Dump(dc);
}
#endif //_DEBUG


// CBibleForm message handlers

void CBibleForm::OnSize(UINT nType, int cx, int cy)
{
	CFormView::OnSize(nType, cx, cy);

	
	// TODO: Add your message handler code here
	if(cx < 50 || cy < 50) return;

	// TODO: Add your message handler code here

	if(isSheet == FALSE) return;  // return if propertysheet has not been created yet

	CWnd* pwndPropSheetHolder = GetDlgItem(IDC_PLACEHOLDER);

	if(::IsWindow(pwndPropSheetHolder->GetSafeHwnd())) {
		pwndPropSheetHolder ->SetWindowPos(NULL,0,0,cx,cy ,SWP_NOZORDER | SWP_NOACTIVATE);
	
	CRect rectHolder;
	CRect rectSheet;
	pwndPropSheetHolder->GetWindowRect(rectHolder);
	m_pMyPropSheet ->GetWindowRect(rectSheet);
	m_pMyPropSheet ->ScaleSheet(rectHolder.Height() - rectSheet.Height(),
					rectHolder.Width() - rectSheet.Width());
}
	// end if
	

}

void CBibleForm::OnInitialUpdate()
{
	CFormView::OnInitialUpdate();

	// TODO: Add your specialized code here and/or call the base class
	::AfxInitRichEdit2();

	// TODO: Add your specialized code here and/or call the base class
	CWnd* pwndPropSheetHolder = GetDlgItem(IDC_PLACEHOLDER);
	pwndPropSheetHolder->SetParent(this);

	CRect rect;
	GetWindowRect(rect);
	ScreenToClient(rect);
	pwndPropSheetHolder ->SetWindowPos(NULL,0,0,rect.Width(),
		rect.Height(),SWP_NOZORDER | SWP_NOACTIVATE);
		/////////////////////////////////////////////////////////////////////////

	// create the sheet
	if(objCount == 1)	// creation of main Bible view
    m_pMyPropSheet = new CBibleSheet(AFX_MAINBIBLE,pwndPropSheetHolder);

	if(objCount == 2)   // creation of bottom view
	m_pMyPropSheet = new CBibleSheet(AFX_BOTTOM,pwndPropSheetHolder);

	if(objCount == 3)   // creation of bottom left view
		m_pMyPropSheet = new CBibleSheet(AFX_BOTTOMLEFT,pwndPropSheetHolder);
	
	if (!m_pMyPropSheet->Create(pwndPropSheetHolder, 
		WS_CHILD| WS_VISIBLE , 0))
	{
		delete m_pMyPropSheet;
		m_pMyPropSheet = NULL;
		return;
	}

	isSheet = TRUE;			// The Bible property sheet has been created
	
	// fit the property sheet into the place holder window, and show it
	CRect rectHolder;
	CRect rectSheet;
	pwndPropSheetHolder->GetWindowRect(rectHolder);
	m_pMyPropSheet ->GetWindowRect(rectSheet);

	
	
	if( ::IsWindow(m_pMyPropSheet ->GetSafeHwnd()) &&
		::IsWindow(pwndPropSheetHolder ->GetSafeHwnd())    )

		m_pMyPropSheet ->ScaleSheet(rectHolder.Height() - rectSheet.Height(),
									rectHolder.Width() - rectSheet.Width());
      
	SetScrollSizes(MM_TEXT,CSize(0,0));

	



}

void CBibleForm::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{

	
	if (::GetDeviceCaps(pDC->m_hDC, TECHNOLOGY) != DT_METAFILE && pDC->m_hAttribDC != NULL)
	{
	::ScaleWindowExtEx(pDC->m_hDC,
	::GetDeviceCaps(pDC->m_hDC, LOGPIXELSX),
	::GetDeviceCaps(pDC->m_hAttribDC, LOGPIXELSX),
	::GetDeviceCaps(pDC->m_hDC, LOGPIXELSY),
	::GetDeviceCaps(pDC->m_hAttribDC, LOGPIXELSY), NULL);
	}


	long		lLineWidth = ::MulDiv(pDC->GetDeviceCaps(PHYSICALWIDTH), 1440, pDC->GetDeviceCaps(LOGPIXELSX));
	FORMATRANGE	fmtRange;
	CRect		rect;
	CRect		page;
	int			last = 0;

	// get the page size in twips (1440 twips/inch)
	page.left = 0;
	page.top = 0;
	page.right = ::MulDiv(pDC->GetDeviceCaps(PHYSICALWIDTH), 1440, pDC->GetDeviceCaps(LOGPIXELSX));
	page.bottom = ::MulDiv(pDC->GetDeviceCaps(PHYSICALHEIGHT), 1440, pDC->GetDeviceCaps(LOGPIXELSY));

	rect = page;

	rect.DeflateRect(720,720,720, 1440); /* 720 twips or 0.5 inches margins */

    // setup the format range attributes
	fmtRange.hdc = pDC->m_hDC;
	fmtRange.hdcTarget = pDC->m_hAttribDC;
	fmtRange.rc = rect;
	fmtRange.rcPage = page;
	


	pDC->SaveDC();


	// determine the correct output for this page
	pControl->SetTargetDevice(*pDC, lLineWidth);


	for (UINT i = 0 ; i < pInfo->m_nCurPage ; i++)
	{
		
		fmtRange.rc = rect;
		fmtRange.chrg.cpMin = last;
		fmtRange.chrg.cpMax = -1;
		// measure the data that goes on this page, just measuring, not displaying
		if (i < pInfo->m_nCurPage-1) {
                  last = pControl->FormatRange(&fmtRange, FALSE);
				  pControl->FormatRange(NULL, FALSE); 
		}
		else  pControl->FormatRange(&fmtRange, TRUE); /* Formats a range of text in a rich edit control for a specific device
															 Typically, this call is followed by a call to DisplayBand */
	
		// when we drop out of the loop, we should print the correct part of the output for the current page
	}

	// Update the display with the new formatting.
	RECT rcClient;
	pControl->GetClientRect(&rcClient);
	pControl->DisplayBand(&rcClient);
	pControl->FormatRange(NULL, FALSE);	// release the cached DC information stored in SetTargetDevice
	pDC->RestoreDC(-1);

	
	CFormView::OnPrint(pDC, pInfo);
}

BOOL CBibleForm::OnPreparePrinting(CPrintInfo* pInfo)
{

	CDC			dc;
	CRect		page;
	FORMATRANGE	fmtRange;
	long		lLineWidth;
	int			last = 0;

	AfxGetApp()->CreatePrinterDC(dc);
    if (!dc.m_hDC)
    {
        AfxMessageBox(_T("Failed to get printer DC\n"));
        return FALSE;
    }

	dc.SaveDC();

	pInfo->SetMaxPage(0);
	// get the page size in twips (1440 twips/inch)
	page.left = 0;
	page.top = 0;
	page.right = ::MulDiv(dc.GetDeviceCaps(PHYSICALWIDTH), 1440, dc.GetDeviceCaps(LOGPIXELSX));
	page.bottom = ::MulDiv(dc.GetDeviceCaps(PHYSICALHEIGHT), 1440, dc.GetDeviceCaps(LOGPIXELSY));
	lLineWidth = page.right;

	CRect rect = page;
	rect.DeflateRect(720,720,720, 1440); /* 720 twips or 0.5 inches margins */

	// setup the format range attributes
	fmtRange.hdc = dc.m_hDC;
	fmtRange.hdcTarget = dc.m_hAttribDC;
	fmtRange.rc = rect;
	fmtRange.rcPage = page;

	// determine the correct output for this page
	pControl->SetTargetDevice(dc, lLineWidth);
	
	long len = pControl->GetTextLengthEx(GTL_PRECISE);
	
	while (last < len )
	{
		fmtRange.chrg.cpMin = last;
		fmtRange.chrg.cpMax = -1;
		// measure the data that goes on this page
		last = pControl->FormatRange(&fmtRange, FALSE);	// just measuring, not displaying
		pInfo->SetMaxPage(pInfo->GetMaxPage() + 1);
	}

	pInfo->SetMaxPage(pInfo->GetMaxPage() + 1);

    pControl->FormatRange(NULL, FALSE);	// release the cached DC information stored in SetTargetDevice
	
	dc.RestoreDC(-1);
	dc.DeleteDC();

	return DoPreparePrinting(pInfo);	
}




LONG CBibleForm::OnPrintMessage(UINT wp, LONG lp)
{
	if(objCount != wp) return 0L; // controls which form instance should process the printing request
	CFormView::OnFilePrintPreview();
	return 0L;

}



void CBibleForm::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
{
  CFormView::OnBeginPrinting(pDC, pInfo);
}



void CBibleForm::OnEndPrintPreview(CDC* pDC, CPrintInfo* pInfo, POINT point, CPreviewView* pView)
{
	    
	CFormView::OnEndPrintPreview(pDC, pInfo, point, pView);
	CFormView ::OnFilePrint();

		
}